import { typedHttp } from '@/utils/typedHttp';
import type { ComplianceItem, Attachment } from '@/types/work';

export interface ComplianceItemsQuery {
  assessment_plan_id?: string;
  title?: string;
  compliance_type?: string;
  risk_level?: string;
  compliance_status?: string;
  progress_status?: string;
  inspector?: string;
  skip?: number;
  limit?: number;
}

interface ComplianceItemPagination {
  total: number;
  items: ComplianceItem[];
}

/**
 * Fetch compliance items from backend API with optional filters and pagination
 * @param query Optional query parameters for filtering and pagination
 * @returns Promise resolving to an array of ComplianceItem
 */
export async function fetchComplianceItems(query: ComplianceItemsQuery = {}): Promise<ComplianceItem[]> {
  // We need to fetch all pages until we have retrieved `total` items returned by the API.
  // The backend supports classic skip/limit pagination (default limit 100). We iterate
  // by increasing the `skip` value until we have collected the full list.

  const allItems: ComplianceItem[] = [];
  let fetchedTotal = 0; // number of items already retrieved
  let totalItems = Infinity; // initialise with Infinity so that the first request is always triggered

  // Honour caller-supplied pagination parameters but fall back to API defaults
  const limit = query.limit ?? 100;
  let skip = query.skip ?? 0;

  // Query parameters that remain constant across requests (everything except skip)
  const staticQuery: Omit<ComplianceItemsQuery, 'skip'> = { ...query };
  delete (staticQuery as Partial<ComplianceItemsQuery>).skip; // ensure skip is not duplicated
  delete (staticQuery as Partial<ComplianceItemsQuery>).limit; // we control limit explicitly

  while (fetchedTotal < totalItems) {
    // Build URLSearchParams for the current request
    const params = new URLSearchParams();
    Object.entries({ ...staticQuery, skip, limit }).forEach(([key, value]) => {
      if (value !== undefined && value !== null) {
        params.append(key, String(value));
      }
    });

    const response = await typedHttp.get<ComplianceItemPagination>(`/compliance-items/?${params.toString()}`);

    // Update counters and accumulate items
    if (totalItems === Infinity) totalItems = response.total;

    allItems.push(...response.items);
    fetchedTotal += response.items.length;
    skip += response.items.length;

    // Safety valve: break if the server returns 0 items to avoid infinite loops
    if (response.items.length === 0) {
      break;
    }
  }

  return allItems;
}

/**
 * Add a new compliance item via backend API
 * @param item ComplianceItem to add
 * @returns Promise resolving to the added ComplianceItem
 */
export async function addComplianceItem(item: ComplianceItem): Promise<ComplianceItem> {
  return typedHttp.post('/compliance-items/', item);
}

/**
 * Update an existing compliance item via backend API
 * @param item ComplianceItem to update
 * @returns Promise resolving to the updated ComplianceItem
 */
export async function updateComplianceItem(item: ComplianceItem): Promise<ComplianceItem> {
    
  const { attachments, related_guarantees, ...rest } = item;
  return typedHttp.put(`/compliance-items/${item.id}`, rest);
}

/**
 * Delete a compliance item by ID via backend API
 * @param id ID of the ComplianceItem to delete
 * @returns Promise resolving to deletion result
 */
export async function deleteComplianceItem(id: string): Promise<void> {
  return typedHttp.delete(`/compliance-items/${id}/`);
}

/**
 * Upload an attachment for a compliance item
 * @param complianceItemId ID of the compliance item
 * @param file File to upload
 * @returns Promise resolving to the uploaded Attachment
 */
export async function uploadAttachment(complianceItemId: string, file: File): Promise<Attachment> {
  const formData = new FormData();
  formData.append('file', file);
  
  return typedHttp.post<Attachment>(
    `/attachments/${complianceItemId}`, 
    formData,
    {
      headers: {
        'Content-Type': 'multipart/form-data'
      }
    }
  );
}

/**
 * Get an attachment file
 * @param attachmentId ID of the attachment to retrieve
 * @returns Promise resolving to the file Blob
 */
export async function getAttachmentFile(attachmentId: string): Promise<Blob> {
  return typedHttp.get<Blob>(
    `/attachments/${attachmentId}`,
    {
      responseType: 'blob'
    }
  );
}

/**
 * Delete an attachment
 * @param attachmentId ID of the attachment to delete
 * @returns Promise resolving when deletion is complete
 */
export async function deleteAttachment(attachmentId: string): Promise<void> {
  return typedHttp.delete(`/attachments/${attachmentId}`);
}

/**
 * Get all attachments for an assessment plan
 * @param assessmentPlanId ID of the assessment plan
 * @returns Promise resolving to an array of Attachments
 */
export async function getAssessmentPlanAttachments(assessmentPlanId: string): Promise<Attachment[]> {
  return typedHttp.get<Attachment[]>(`/attachments/assessment-plan/${assessmentPlanId}`);
}

/**
 * Copy existing attachments to a compliance item (creates new files and records)
 * @param complianceItemId ID of the compliance item
 * @param attachmentIds Array of attachment IDs to copy
 * @returns Promise resolving to an array of newly created attachment records
 */
export async function copyExistingAttachments(complianceItemId: string, attachmentIds: string[]): Promise<Attachment[]> {
  return typedHttp.post<Attachment[]>(
    `/attachments/copy/${complianceItemId}`,
    { attachment_ids: attachmentIds }
  );
}

/**
 * Export all attachments for an assessment plan as a zip file
 * @param assessmentPlanId ID of the assessment plan
 * @returns Promise resolving to the zip file Blob
 */
export async function exportAssessmentPlanAttachments(assessmentPlanId: string): Promise<Blob> {
  return typedHttp.get<Blob>(
    `/attachments/export/${assessmentPlanId}`,
    {
      responseType: 'blob'
    }
  );
}

export default {
  fetchComplianceItems,
  addComplianceItem,
  updateComplianceItem,
  deleteComplianceItem,
  uploadAttachment,
  getAttachmentFile,
  deleteAttachment,
  getAssessmentPlanAttachments,
  copyExistingAttachments,
  exportAssessmentPlanAttachments
};